package com.tqjc.system.core.task;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.tqjc.system.common.constant.AddTaskConstant;
import com.tqjc.system.common.constant.GlobalConstant;
import com.tqjc.system.common.entity.BO.AreaScanStatusBO;
import com.tqjc.system.common.entity.BO.TankScanStatusResBO;
import com.tqjc.system.common.enums.AlarmStatusEnum;
import com.tqjc.system.common.enums.ScannerInfoEnum;
import com.tqjc.system.core.pipeline.util.ScanUtils;
import com.tqjc.system.core.redis.RedisApi;
import com.tqjc.system.core.scan.thread.AsynTankCarScanThread;
import com.tqjc.system.core.threadpool.ThreadPoolManager;
import com.tqjc.system.core.websocket.TaskExecutionWebSocketService;
import com.tqjc.system.system.asyn.AsynRestartAreaScannerThread;
import com.tqjc.system.system.entity.SysAlarmInfoEntity;
import com.tqjc.system.system.service.SysAlarmInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

/**
 * @description:  监控扫描仪状态任务
 * @Author: 86195
 * @Date: 2024/1/8 15:53
 **/
@Component
@Slf4j
public class MonitorScannerStatusTask {


    @Autowired
    private SysAlarmInfoService alarmInfoService;

    @Autowired
    private TaskExecutionWebSocketService taskExecutionWebSocketService;

    @Autowired
    private RedisApi redisApi;


    private Map<String,Long> map = new HashMap<>(4);


    //每30秒执行一次
    @Scheduled(cron = "0/30 * * * * ?")
    public void monitor(){

        for (ScannerInfoEnum value : ScannerInfoEnum.values()) {
            //当前状态值为正常  false：没有异常
            boolean flag = false;
            String carName = value.getDesc();
            if(value.getTaskType() == 0){
                //槽车扫描仪定时任务执行
                TankScanStatusResBO scannerStatus = ScanUtils.getScannerStatus(value.getScannerType());
                if(scannerStatus != null){
                    float pollution = scannerStatus.getPollution();
                    if(pollution < 65){
                        log.error("{}:扫描仪污染值不合格，当前值为：{}",carName,pollution);
                        saveFaultInfo(carName,"扫描仪污染值不合格。当前污染值为："+pollution,false,"扫描仪污染值不合格");
                        flag = true;
                    }

                    if(pollution < 75){
                        log.error("{}:扫描仪污染值已低于预警值75，当前值为：{}",carName,pollution);
                        saveFaultInfo(carName,"扫描仪污染值已低于预警值75,低于65将不可用。请及时清理扫描仪。当前污染值为："+pollution,false,"扫描仪污染值预警");
                        flag = true;
                    }

                    float temperature = scannerStatus.getTemperature();
                    if( 20 > temperature  || temperature > 65 ){
                        log.error("{}:扫描仪温度值不合格，当前值为：{}",carName,temperature);
                        saveFaultInfo(carName,"扫描仪温度值不合格。当前温度值为："+temperature,false,"扫描仪温度值不合格");
                        flag = true;
                    }
                }
            } else {
                //库区扫描仪定时任务执行
                String tag = value.getRedisTag();
                String redisTag = new StringBuilder("DeviceStatusInfo").append(tag).toString();
                JSONObject jsonObject = (JSONObject) redisApi.get(redisTag);
                if(jsonObject == null){
                    log.error("{}:扫描仪redis中无数据",carName);
                    saveFaultInfo(carName,"本扫描仪redis中无数据",false,"本扫描仪redis中无数据");
                    continue;
                }
                AreaScanStatusBO areaScanStatusBO = jsonObject.toJavaObject(AreaScanStatusBO.class);
                //上一次时间戳
                Long lastTimeStampObj = map.get(tag);
                long lastTimeStamp = lastTimeStampObj == null ? 0l : lastTimeStampObj.longValue();
                //本次返回的时间戳
                long timeStamp = areaScanStatusBO.getTimeStamp();
                if(timeStamp != lastTimeStamp){
                    //上一次返回的时间戳，与本次不一样表示正常  更新时间戳
                    map.put(tag,timeStamp);
                } else {
                    log.error("{}:扫描仪返回时间戳数值与上一次相同，时间戳数值为:{}",carName,lastTimeStamp);
                    saveFaultInfo(carName,"本扫描仪返回时间戳数值与上一次相同，时间戳数值为："+lastTimeStamp,false,"本扫描仪返回时间戳数值与上一次相同");
                    continue;
                }

                Float pollution = areaScanStatusBO.getPollution();
                if(pollution < 65){
                    flag = true;
                    log.error("{}:扫描仪污染值不合格，当前值为：{}",carName,pollution);
                    saveFaultInfo(carName,"扫描仪污染值不合格。当前污染值为："+pollution,false,"扫描仪污染值不合格");
                }

                if(pollution < 75){
                    flag = true;
                    log.error("{}:扫描仪污染值已低于预警值75，当前值为：{}",carName,pollution);
                    saveFaultInfo(carName,"扫描仪污染值已低于预警值75,低于65将不可用。请及时清理扫描仪。当前污染值为："+pollution,false,"扫描仪污染值预警");
                }

                Float temperature = areaScanStatusBO.getTemperature();
                if( 20 > temperature  || temperature > 65 ){
                    flag = true;
                    log.error("{}:扫描仪温度值不合格，当前值为：{}",carName,temperature);
                    saveFaultInfo(carName,"扫描仪温度值不合格。当前温度值为："+temperature,false,"扫描仪温度值不合格");
                }
                String scanStat = areaScanStatusBO.getScanStat();
                if(!GlobalConstant.AREA_SCANNER_NORMAL_STATUS.equals(scanStat)){
                    flag = true;
                    log.error("{}:服务与扫描仪的连接状态异常，当前值为：{}",carName,scanStat);
                    saveFaultInfo(carName,"服务与扫描仪的连接状态异常。当前状态值为："+scanStat,false,"服务与扫描仪的连接状态异常");
                }

                String plcStat = areaScanStatusBO.getPlcStat();
                if(!GlobalConstant.AREA_SCANNER_NORMAL_STATUS.equals(plcStat)){
                    flag = true;
                    log.error("{}:服务与PLC的连接状态异常，当前值为：{}",carName,plcStat);
                    saveFaultInfo(carName,"服务与PLC的连接状态异常。当前状态值为："+plcStat,false,"服务与PLC的连接状态异常");
                }

                String redisStat = areaScanStatusBO.getRedisStat();
                if(!GlobalConstant.AREA_SCANNER_NORMAL_STATUS.equals(redisStat)){
                    flag = true;
                    log.error("{}:服务与redis的连接状态异常，当前值为：{}",carName,redisStat);
                    saveFaultInfo(carName,"服务与redis的连接状态异常。当前状态值为："+redisStat,false,"服务与redis的连接状态异常");
                }

                Boolean neededRebootScan = areaScanStatusBO.getNeededRebootScan();
                if(neededRebootScan){
                    flag = true;
                    log.error("{}:需要断电重启扫描仪，当前值为：{}",carName,neededRebootScan);
                    saveFaultInfo(carName,"需要断电重启扫描仪。当前状态值为："+neededRebootScan,true,"需要断电重启扫描仪");
                }


            }

            //判断异常是否完成
            if(!flag){
                //当地扫描仪没有异常，将之前的异常报警信息翻转至正常
                log.info("{}：此刻没有异常，翻转正常的状态");
                //查看当前天车是否存在异常
                int count = alarmInfoService.count(new LambdaQueryWrapper<SysAlarmInfoEntity>().eq(SysAlarmInfoEntity::getCarName, carName)
                        .in(SysAlarmInfoEntity::getStatus, AlarmStatusEnum.ALARM_STATUS_INIT.getStatus(),AlarmStatusEnum.ALARM_STATUS_ERROR.getStatus())
                        .ge(SysAlarmInfoEntity::getCreateDate, LocalDateTime.now().minusDays(3)));
                if(count > 0){
                    alarmInfoService.update(new LambdaUpdateWrapper<SysAlarmInfoEntity>().eq(SysAlarmInfoEntity::getCarName,carName)
                            .in(SysAlarmInfoEntity::getStatus, AlarmStatusEnum.ALARM_STATUS_INIT.getStatus(),AlarmStatusEnum.ALARM_STATUS_ERROR.getStatus())
                            .set(SysAlarmInfoEntity::getUpdateDate,LocalDateTime.now())
                            .set(SysAlarmInfoEntity::getStatus, AlarmStatusEnum.ALARM_STATUS_DONE.getStatus())
                            .ge(SysAlarmInfoEntity::getCreateDate, LocalDateTime.now().minusDays(3)));
                }

            }



        }

    }


    /**
     *
     * @param carName  异常位置
     * @param errMsg  异常信息
     * @param isHandle 异常是否需要处理
     */
    private void saveFaultInfo(String carName,String errMsg,boolean isHandle,String type){
        //判断近一周内该异常信息是否已出现且未处理   是则需要插入数据
        int count = alarmInfoService.isNewAlarmInfo(carName,type);
        if(count <= 0){
            SysAlarmInfoEntity alarmInfoEntity = SysAlarmInfoEntity.builder().carName(carName).type(type).errMsg(errMsg).build();
            alarmInfoService.save(alarmInfoEntity);
            Map map = new HashMap(1);
            map.put("code","10");
            taskExecutionWebSocketService.sendMessage(map);
            if(isHandle){
                ThreadPoolManager.getInstance().execute(AsynRestartAreaScannerThread.builder().alarmInfo(alarmInfoEntity).build());
            }

        }
    }





}
